home *** CD-ROM | disk | FTP | other *** search
- /* File: tutils.c
- Copyright Norman Wilde 1993
- Notes: code for utilities used in testing system
- */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #include "tutils.h"
- /* ----------- buffer for strings, blocks, etc. ------------- */
- #define MAXCOLLECT 10000
- char collectBuf[MAXCOLLECT] = {'\0'}; /* reserve space for buffer*/
- char * collectPos = collectBuf; /* points to next free space in buffer*/
- void collect(char c) { /* collect char c into the buffer */
- *collectPos++ = c;
- assert(collectPos - collectBuf < MAXCOLLECT); // abort if buf overflows
- }
- void collectFirst(char c) { /* reset buf and collect c */
- collectPos = collectBuf;
- collect(c);
- }
- char * release() { /* copy the string in the buf to the
- heap, terminate it, and return the copy*/
- char * t = (char *) calloc(sizeof (char), collectPos - collectBuf + 1);
- char * s;
- char * i;
- s = t;
- assert ( t > 0);
- for (i = collectBuf; i < collectPos; )
- *t++ = *i++;
- *t = '\0';
- return s;
- }
- /* ----------- simple linked list of strings with data---------------- */
- struct STRLIST * listNew(char* aStr, void * aData) {
- /* Answer a new list with aStr as only element */
- struct STRLIST *t = (struct STRLIST *) malloc(sizeof(struct STRLIST));
- t->str = aStr;
- t->data = aData;
- t->next = NULL;
- return t;
- }
- struct STRLIST * listAdd(struct STRLIST * aList,char* aStr, void * aData) {
- /* Add aStr to aList */
- struct STRLIST *t = (struct STRLIST *) malloc(sizeof(struct STRLIST));
- t->str = aStr;
- t->data = aData;
- t->next = aList;
- return t;
- }
- void * listFind(struct STRLIST * aList, char * aStr) {
- /* Locate string matching aStr in aList. Answer the data ptr. if
- found, NULL if not found */
- struct STRLIST * v;
- for(v = aList; v != NULL; v = v->next) {
- if(strcmp(aStr,v->str) ==0) break;
- }
- if(v==NULL)
- return NULL;
- else
- return v->data;
- }
- int listSize(struct STRLIST *aList) {
- /* Answer the number of elements in the list */
- struct STRLIST * v;
- int size = 0;
- for(v = aList; v != NULL; v = v->next)
- size++;
- return size;
- }
- /* --- routines to create the test driver program ------- */
- #define FBUFSIZE 10000 /*size of some internal bufs */
- static char Buffer[FBUFSIZE]; /*assemble strings as needed */
- static char r_name[21] = {'\0'}; /*name given in the runtest
- stmt currently being processed*/
- static char * MainDecls = NULL; /*store on heap the declarations in
- the main fcn being built */
- static char * MainStmts = NULL; /*store on heap the statements in
- the main fcn beint built */
- static void addMainDecls(char * decls) {
- /* append to MainDecls a copy of the string in decls */
- char * temp;
- if(MainDecls == NULL) {
- MainDecls = calloc(strlen(decls) + 1, sizeof(char));
- strcpy(MainDecls, decls);
- return;
- } else {
- temp = calloc(strlen(decls) + strlen(MainDecls) + 1, sizeof(char));
- strcpy(temp, MainDecls);
- strcat(temp, decls);
- free(MainDecls);
- MainDecls = temp;
- return;
- }
- }
- static void addMainStmts(char * stmts) {
- /* append to MainStmts a copy of the string in stmts */
- char * temp;
- if(MainStmts == NULL) {
- MainStmts = calloc(strlen(stmts) + 1, sizeof(char));
- strcpy(MainStmts, stmts);
- return;
- } else {
- temp = calloc(strlen(stmts) + strlen(MainStmts) + 1, sizeof(char));
- strcpy(temp, MainStmts);
- strcat(temp, stmts);
- free(MainStmts);
- MainStmts = temp;
- return;
- }
- }
- void addBlock(char * block) {
- /* add to the driver the given embedded block */
- /* remove first '{' and last '}' */
- char * tmpStr = calloc(strlen(block), sizeof(char));
- strncat(tmpStr, block + 1, strlen(block) -2);
- printf("%s\n", tmpStr);
- free(tmpStr);
- }
-
- void setRunName(char * theRName) {
- /* set the name of the test run to the frist 20 chars of theRName*/
- strncpy(r_name, theRName, 20);
- }
- static char * getArgDeclStr(struct STRLIST *varList) {
- /* Answer a string on the heap with a comma separated list of the
- variables in varList formatted as:
- <argtype> var, <argtype>var,
- suitable for a function's argument declarations.
- */
- char * res, * remainder, * type;
- int thisVarLength, resultLength;
- if(varList == NULL) return NULL;
- type = getVarArgType(varList->str);
- thisVarLength = strlen(varList->str) + strlen(type) + 3;
- if(varList->next == NULL){
- res = calloc(thisVarLength + 1, sizeof (char) );
- sprintf(res, "%s %s", type, varList->str);
- return res;
- }
- remainder = getArgDeclStr( varList->next);
- resultLength = strlen(remainder) + thisVarLength + 1;
- res = calloc(resultLength + 1, sizeof (char) );
- sprintf(res, "%s %s,%s", type, varList->str, remainder);
- free(remainder);
- return res;
- }
- static char * genFcnString(
- char * run_name,
- char * fcn_name,
- struct STRLIST *varList,
- char* body) {
- /* Answer function string (on heap) for first variable in list*/
- char * declarations; /*decls for var. varList->str*/
- int n; /*num. chars assembled */
- char * theFunc; /*the result function string*/
- char * remainingVars; /*string with vars after this*/
- /* must have at least one variable in the list */
- assert( varList != NULL );
- declarations = getVarDeclStr(varList->str);
- if(varList->next != NULL) {
- remainingVars = getArgDeclStr(varList->next);
- n = sprintf(Buffer,"void %s_%s(int vals[], %s){\n%s%s\n}\n",
- run_name, fcn_name, remainingVars, declarations, body);
- assert(n>0 && n < FBUFSIZE - 2);
- free(remainingVars);
- theFunc = calloc(strlen(Buffer)+1, sizeof(char));
- strcpy(theFunc,Buffer);
- } else {
- n = sprintf(Buffer,"void %s_%s(int vals[]){\n %s%s\n}\n",
- run_name, fcn_name, declarations, body);
- assert(n>0 && n < FBUFSIZE - 2);
- theFunc = calloc(strlen(Buffer)+1, sizeof(char));
- strcpy(theFunc,Buffer);
- }
- return theFunc;
- }
- static char * genBottomFcnString(
- char * run_name,
- struct STRLIST *varList,
- char* body) {
- /* Answer function string (on heap) for the 'bottom' function
- that contains the actual test code*/
- int n; /*num. chars assembled */
- char * theFunc; /*the result function string*/
- char * remainingVars; /*string with vars after this*/
- /* must have at least one variable in the list */
- assert( varList != NULL );
- remainingVars = getArgDeclStr(varList);
- n = sprintf(Buffer,"void %s_bottom(int vals[], %s)\n%s\n",
- run_name, remainingVars, body);
- assert(n>0 && n < FBUFSIZE - 2);
- free(remainingVars);
- theFunc = calloc(strlen(Buffer)+1, sizeof(char));
- strcpy(theFunc,Buffer);
- return theFunc;
- }
- static char * getVarNameStr(struct STRLIST *varList) {
- /* Answer a string on the heap with a comma separated list of the
- variables in varList. If there are no variables, return
- an empty string.
- */
- char * res, * remainder;
- int thisVarLength, resultLength;
- if(varList == NULL) /* if no variables, return empty str */
- return calloc(1, sizeof (char) );
- thisVarLength = strlen(varList->str);
- if(varList->next == NULL){
- res = calloc(thisVarLength + 1, sizeof (char) );
- sprintf(res, "%s", varList->str);
- return res;
- }
- remainder = getVarNameStr( varList->next);
- resultLength = strlen(remainder) + thisVarLength + 1;
- res = calloc(resultLength + 1, sizeof (char) );
- sprintf(res, "%s,%s", varList->str, remainder);
- free(remainder);
- return res;
- }
-
- static char * genArgString(struct STRLIST *varList) {
- /* Answer a string (on heap) of the form:
- <1stvar>[vals[n-1]], <2ndvar>, ...<nthvar>
- */
- int n = listSize(varList); /* elements in varList */
- int m;
- char * theStr, * theRest;
- if(varList == NULL) /* return a pointer to a '\0' on the heap */
- return ((char *) calloc(1, sizeof(char)));
- theRest = getVarNameStr(varList->next);
- if(strlen(theRest) > 0)
- m = sprintf(Buffer, "%s[vals[%i]],%s", varList->str, n-1, theRest);
- else
- m = sprintf(Buffer, "%s[vals[%i]]", varList->str, n-1);
- assert(m>0 && m < FBUFSIZE - 2);
- theStr = calloc(strlen(Buffer)+1, sizeof(char));
- strcpy(theStr,Buffer);
- free(theRest);
- return theStr;
- }
-
- static char * genNextBodyString(
- char * run_name,
- char * suffex,
- struct STRLIST *varList) {
- /* Answer a string (on heap) for the body of the next
- function down the list. Contains a function call:
- <run_name>_<suffex>(vals, <arguments in varList>);
- */
- char * varNameStr = genArgString(varList); /*vars with subscripts*/
- char * nextBody; /*heap space for next body */
- int n; /*num. chars assembled */
- n = sprintf(Buffer," %s_%s(vals,%s);\n",
- run_name,suffex,varNameStr);
- assert(n>0 && n < FBUFSIZE - 2);
- nextBody = calloc(strlen(Buffer)+1, sizeof(char));
- strcpy(nextBody,Buffer);
- return nextBody;
- }
- static struct STRLIST * makeVarFuncs(
- char * run_name,
- struct STRLIST *varList,
- char* body) {
- /* Answer a list of strings that are test functions for each
- variable in varList. Each test function has the form:
- void <run_name>_<var>(int vals[], <other args>) {
- <declaration of array for variable var>
- <body>
- }
- The body is a call to the previous function in the list
- */
- struct STRLIST * funcList = NULL; /*fcns after this one */
- char * nextBody; /*heap space for next body */
- char * theFunc; /*heap space for this fcn */
- int n; /*num. chars assembled */
- /* must have at least one variable in the list */
- assert( varList != NULL );
- if(varList->next != NULL) {
- /* Generate functions for the rest of the variable list - recursive*/
- nextBody = genNextBodyString(run_name, varList->str, varList->next);
- funcList = makeVarFuncs(run_name, varList->next, nextBody);
- theFunc = genFcnString(run_name, varList->str, varList, body);
- return (listAdd(funcList, theFunc, ""));
- }
- else {
- theFunc = genFcnString(run_name, varList->str, varList, body);
- return (listNew(theFunc, ""));
- };
- }
- static char * getLastVar(struct STRLIST *varList) {
- /* Answer the string with the name of the last variable in varList */
- struct STRLIST * v;
- assert(varList != NULL);
- for(v = varList; v->next != NULL; v = v->next) ; /* empty loop */
- return v->str;
- }
- static char * getNumValsStr(struct STRLIST *varList) {
- /* Answer a string on the heap with a comma separated list of the
- number of values of each variable in varList formatted as:
- <vals_lastVar>,...,<vals_firstVar>
- suitable for an array declaration
- */
- char * res, * remainder;
- int thisVarNumVals;
- assert(varList != NULL);
- thisVarNumVals =
- getVarNumVals(varList->str); /* values of first var on list */
- assert(thisVarNumVals > 0);
- if(varList->next != NULL) {
- remainder = getNumValsStr(varList->next);
- sprintf(Buffer, "%s,%i", remainder, thisVarNumVals);
- free(remainder);
- } else {
- sprintf(Buffer,"%i", thisVarNumVals);
- }
- res = calloc(strlen(Buffer) + 1, sizeof (char) );
- strcpy(res,Buffer);
- return res;
- }
-
- void makeVary(struct STRLIST * varList, char * block) {
- struct STRLIST * v, * t;
- char * nextBody; /*body of the first level function */
- char * theFunc; /*generated top level function */
- char * numValsStr; /*str with max values of each variable */
- int numVars; /*no. of variables in varList */
- char * top_var; /*name of last variable in varList */
- int m;
- assert( varList != NULL); /* must have at least one variable */
- nextBody = genNextBodyString(r_name, "bottom", varList);
- v = makeVarFuncs(r_name, varList, nextBody);
- theFunc = genBottomFcnString(r_name, varList, block);
- v = listAdd(v, theFunc, "");
- /* write the generated functions to stdout */
- for( t = v; t != NULL; t = t->next )
- printf("%s\n", t->str);
- /* WRITE THE FOLLOWING TO THE MAIN
- int nvals_<r_name>[<links in varList>]={<list of no. of vals of each var - rev.order>};
- Test_gen_varying g_<r_name>(<links in varList>,nvals_<r_name>);
- int vals_<r_name>[<links in varList>]={-1};
- while (g_<r_name>.next_vector(vals_<r_name>) == YES) {
- <r_name>_<name of last var>(vals_<r_name>);
- };
- */
- numValsStr = getNumValsStr(varList);
- numVars = listSize(varList);
- top_var = getLastVar(varList);
- m = sprintf(Buffer, /* declarations for the main */
- "int nvals_%s[%i] = { %s };\n"
- "Test_gen_varying g_%s(%i, nvals_%s);\n"
- "int vals_%s[%i] = { -1 };\n",
- r_name,numVars,numValsStr,
- r_name,numVars,r_name,
- r_name,numVars);
- assert( m > 0 && m < FBUFSIZE - 2);
- addMainDecls(Buffer);
- m = sprintf(Buffer, /* statements for the main */
- "while (g_%s.next_vector(vals_%s) == YES) {\n"
- " %s_%s(vals_%s);\n"
- "};\n",
- r_name,r_name,
- r_name,top_var,r_name);
- assert( m > 0 && m < FBUFSIZE - 2);
- addMainStmts(Buffer);
- }
-
- void makeComb(struct STRLIST * varList, char * block) {
- struct STRLIST * v, * t;
- char * nextBody; /*body of the first level function */
- char * theFunc; /*generated top level function */
- char * numValsStr; /*str with max values of each variable */
- int numVars; /*no. of variables in varList */
- char * top_var; /*name of last variable in varList */
- int m;
- assert( varList != NULL); /* must have at least one variable */
- nextBody = genNextBodyString(r_name, "bottom", varList);
- v = makeVarFuncs(r_name, varList, nextBody);
- theFunc = genBottomFcnString(r_name, varList, block);
- v = listAdd(v, theFunc, "");
- /* write the generated functions to stdout */
- for( t = v; t != NULL; t = t->next )
- printf("%s\n", t->str);
- /* WRITE THE FOLLOWING TO THE MAIN
- int nvals_<r_name>[<links in varList>]={<list of no. of vals of each var - rev.order>};
- Test_gen_combining g_<r_name>(<links in varList>,nvals_<r_name>);
- int vals_<r_name>[<links in varList>]={-1};
- while (g_<r_name>.next_vector(vals_<r_name>) == YES) {
- <r_name>_<name of last var>(vals_<r_name>);
- };
- */
- numValsStr = getNumValsStr(varList);
- numVars = listSize(varList);
- top_var = getLastVar(varList);
- m = sprintf(Buffer, /* declarations for the main */
- "int nvals_%s[%i] = { %s };\n"
- "Test_gen_combining g_%s(%i, nvals_%s);\n"
- "int vals_%s[%i] = { -1 };\n",
- r_name,numVars,numValsStr,
- r_name,numVars,r_name,
- r_name,numVars);
- assert( m > 0 && m < FBUFSIZE - 2);
- addMainDecls(Buffer);
- m = sprintf(Buffer, /* statements for the main */
- "while (g_%s.next_vector(vals_%s) == YES) {\n"
- " %s_%s(vals_%s);\n"
- "};\n",
- r_name,r_name,
- r_name,top_var,r_name);
- assert( m > 0 && m < FBUFSIZE - 2);
- addMainStmts(Buffer);
- }
-
- void writeDriver(void) {
- /* write the main function of the driver to standard output */
- printf("void main() {\n%s%s}\n", MainDecls, MainStmts);
- }
-
- /* --- routines to manage a table of all the variables in a test file --- */
- static struct STRLIST * VarTable = NULL; /* The table of variables */
- void addVars(struct STRLIST * vList, char * typeStr, struct STRLIST * iList) {
- /* Add to the table the variables in vList, each of which is
- of type typeStr and has the set of initializors iList */
- struct STRLIST *v;
- struct VARIABLE * newVar;
- for(v = vList; v != NULL; v = v->next) {
- newVar = (struct VARIABLE *) malloc(sizeof(struct VARIABLE));
- newVar->name = v->str;
- newVar->dtype = typeStr;
- newVar->atype = typeStr;
- newVar->inits = iList;
- if(VarTable == NULL)
- VarTable = listNew(v->str, newVar);
- else
- VarTable = listAdd(VarTable, v->str, newVar);
- };
- }
- void addTVars(struct STRLIST * vList, char * decType, char * argType, struct STRLIST * iList) {
- /* Add to the table the variables in vList, each of which is
- of type decType for declarations and type argType for arguments
- and has the set of initializors iList */
- struct STRLIST *v;
- struct VARIABLE * newVar;
- for(v = vList; v != NULL; v = v->next) {
- newVar = (struct VARIABLE *) malloc(sizeof(struct VARIABLE));
- newVar->name = v->str;
- newVar->dtype = decType;
- newVar->atype = argType;
- newVar->inits = iList;
- if(VarTable == NULL)
- VarTable = listNew(v->str, newVar);
- else
- VarTable = listAdd(VarTable, v->str, newVar);
- };
- }
- char * getVarDecType(char * aVar) {
- /* answer a string with the type of the variable, suitable for
- a C/C++ declaration */
- struct VARIABLE *v;
- v = (struct VARIABLE *) listFind(VarTable, aVar);
- if(v == NULL)
- return "DUMMY TYPE";
- else
- return(v->dtype);
- }
- char * getVarArgType(char * aVar) {
- /* answer a string with the type of the variable, suitable for
- a C/C++ function argument declaration */
- struct VARIABLE *v;
- v = (struct VARIABLE *) listFind(VarTable, aVar);
- if(v == NULL)
- return "DUMMY TYPE";
- else
- return(v->atype);
- }
- int getVarNumVals(char * aVar) {
- /* answer the number of values in the set of initializors of
- aVar, or 0 if aVar is not found in the table */
- struct VARIABLE *v;
- v = (struct VARIABLE *) listFind(VarTable, aVar);
- if(v == NULL)
- return 0;
- else
- return(listSize(v->inits));
- }
- static char * genInitsStr(struct STRLIST * inList) {
- /* Answer a string with the initializors in inList, separated
- by ",\n" */
- char * res, * remainder;
- char * thisInit;
- assert(inList != NULL);
- thisInit = inList->str; /* first initializor on list */
- if(inList->next != NULL) {
- remainder = genInitsStr(inList->next);
- sprintf(Buffer, "%s,\n%s", remainder, thisInit);
- free(remainder);
- } else {
- sprintf(Buffer,"%s", thisInit);
- }
- res = calloc(strlen(Buffer) + 1, sizeof (char) );
- strcpy(res,Buffer);
- return res;
- }
- char * getVarDeclStr(char * aVar) {
- /* answer a string with a c/c++ initialized declaration for
- aVar, using all the initializors of the variable */
- struct VARIABLE *v; /* data struct for aVar */
- char * initStr; /* string with the initializors */
- char * res; /* result string */
- v = (struct VARIABLE *) listFind(VarTable, aVar);
- assert (v != NULL); /* the variable must exist */
- initStr = genInitsStr(v->inits);
- sprintf(Buffer, "%s %s[] = {\n%s};\n", getVarDecType(aVar), aVar, initStr);
- res = calloc(strlen(Buffer) + 1, sizeof (char) );
- strcpy(res,Buffer);
- free(initStr);
- return res;
- }